<?php

namespace App\Services;

use App;
use App\Consts;
use App\MeetingReviewProject;
use App\ReviewerGroupProject;
use App\ReviewerScoreProject;
use DB;
use App\Project;
use Illuminate\Support\Facades\Log;

class TestService
{
    public function __construct()
    {
        $this->workflowSvc = new WorkflowService();
        $this->reviewSvc = new ReviewService();
        $this->manageLargeGroupSvc = new ManageLargeGroupService();
    }

    /**
     * 设置大组所有专家可参与评审
     * @param $largeGroupId
     * @author: lxy
     * @time: 2020/6/19 10:51 上午
     * @流程:
     */
    public function setExpertReviewCanAttend($largeGroupId) {
        App\ReviewerGroupReviewer::where('large_group_id',$largeGroupId)
            ->update(['can_attend_review' => 1]);
    }

    /**
     * 自动填充大组回避关键字
     * @param $largeGroupId
     * @author: lxy
     * @time: 2020/6/19 10:50 上午
     * @流程:
     */
    public function autoFillFilterKeywords($largeGroupId){
        $data = DB::table('reviewer_group_reviewers as main')
            ->leftJoin('users as u','main.reviewer_id','=','u.id')
            ->where('main.large_group_id',$largeGroupId)
            ->select('main.*','u.name','u.work_org_name')
            ->get();

        $keywordsGroup = [];
        foreach ($data as $val) {
            $keywordsGroup[$val->reviewer_group_id][] = $val->name;
            $keywordsGroup[$val->reviewer_group_id][] = $val->work_org_name;
        }

        $idsStr = '';
        $updateSql = 'update `reviewer_groups` set keywords = case id ' ;
        foreach ($keywordsGroup as $id => $val) {
            $val = array_unique($val);
            $keywords = implode(',',$val);
            $keywords = trim($keywords);
            $keywords = mb_ereg_replace('[,:;、，：；\s]+', ',', $keywords);
            $idsStr .= $id.',';
            $updateSql .= " when $id then '$keywords' ";
        }
        $idsStr = rtrim($idsStr,',');
        $updateSql .= "end where id in ($idsStr)";

        DB::update($updateSql);
    }


    /**
     * 重置到形式审查阶段
     * @author: lxy
     * @time: 2020/6/11 6:25 下午
     * @流程:
     */
    public function resetSystemDataToFormalReview() {
        // 1) 将组内所有项目状态设置为 B2
        $notStatus = [
            Project::STATUS_FORMAL_REVIEW_FILL_APPLICATION,
            Project::STATUS_FORMAL_REVIEW_RETURNED_TO_FILL
        ];
        $notStatusStr = $this->joinStringValuesForSQL($notStatus);
        DB::statement(
            "update applications set status_id = ?, avg_score = null, ranking = null, ranking_percent = null, large_group_id = null ,planned_award_level = '', final_award_level = '' where status_id not in $notStatusStr",
            [Project::STATUS_FORMAL_REVIEW_TO_REVIEW]
        );

        // 2) 将工作阶段设置为 形式审查
        DB::statement(
            "update workflow_phases set has_begun = 1, has_ended = 0 where phase_id = ?",
            [WorkflowService::PHASE_FORMAL_REVIEW]
        );
        // 2.2) 将大组后续阶段设置为未开始
        DB::statement("update workflow_phases set has_begun = 0, has_ended = 0");
        //开启形式审查阶段
        DB::statement("update workflow_phases set has_begun = 1, has_ended = 0 where phase_id = 'B'");

        // 3) 删除 专家组:
        DB::statement("delete from reviewer_groups");
        // 4) 删除 专家组-专家关系:
        DB::statement("delete from reviewer_group_reviewers");
        // 5) 删除 专家组-项目关系:
        DB::statement("delete from reviewer_group_projects");
        // 6) 删除 专家评分项目数据:
        DB::statement("delete from reviewer_score_projects");
        // 7) 删除 待定区投票数据:
        DB::statement("delete from commissioner_vote_1");
        // 8） 删除 终轮投票数据:

        //删除会评数据
        DB::statement("delete from meeting_review_projects");
//        DB::statement("delete from commissioner_vote_2 where large_group_id = $largeGroupId");
    }

    /**
     * 对所有处于 等待形式审查状态(B2) 的项目，全部通过形式审查
     * @author: lxy
     * @time: 2020/6/11 6:24 下午
     * @流程:
     */
    public function allProjectAdoptFormalReview(){
        try {
            //查询当前待形式审查项目
            $projectList = Project::where('status_id',Project::STATUS_FORMAL_REVIEW_TO_REVIEW)
                ->select('id')
                ->get();

            $Server = new ProjectService();
            foreach ($projectList as  $val) {
                $Server->projectFormalReviewPassed($val['id']);
            }

//            //查询大组信息
//            $largeGroups = \Illuminate\Support\Facades\DB::table('large_groups')->get();
//
//            //初始化更新sql
//            $large_group_id_sql = ' set `large_group_id` = case ';
//            $status_id_sql = ' `status_id` = case ';
//            //更新项目id集合字符串
//            $projectIdsStr = '';
//
//            //遍历项目信息
//            foreach ($projectList as $value) {
//               $awardId = $value->award_id;
//               //匹配项目大组
//               foreach ($largeGroups as $group) {
//                   if ($awardId != $group->award_id) {
//                       continue;
//                   }
//                   if ($awardId == Consts::AWARD_TYPE_TALENT) {
//                       $largeGroupId = $group->id;
//                       $status = Project::STATUS_MEETING_REVIEW_TO_REVIEW;
//                       //拼接sql
//                       $large_group_id_sql .= " when {$value->id} then $largeGroupId";
//                       $status_id_sql .= " when {$value->id} then '{$status}'";
//                       //拼接项目id 逗号分割 用于 IN 条件
//                       $projectIdsStr .= $value->id.',';
//                       break;
//                   }
//                   $largeGroupAttrs = json_decode($group->attrs);
//                   if (in_array($value->prof_category, $largeGroupAttrs->project->prof_fields)) {
//                       $largeGroupId = $group->id;
//                       $status = Project::STATUS_ASSIGN_REVIEW_TO_ASSIGN;
//                       $large_group_id_sql .= " when {$value->id} then $largeGroupId";
//                       $status_id_sql .= " when {$value->id} then '{$status}'";
//                       $projectIdsStr .= $value->id.',';
//                       break;
//                   }
//               }
//            }
//
//            $projectIdsStr = rtrim($projectIdsStr,',');
//            $updateSql = "update `applications` $large_group_id_sql end, $status_id_sql end where id in ($projectIdsStr)";
//            $res = DB::statement($updateSql);
//            if ($res !== true) {
//                throw new \Exception('更新sql执行失败');
//            }
        } catch (\Exception $e) {
            return response()->json(['ok' => false,'msg' =>$e->getMessage()]);
        }
    }



    /**
     * 重置到分配评审阶段
     */
    public function resetSystemDataToAssignProjects($largeGroupId)
    {
        // 1）修改分配评审及后序阶段的项目的状态
        // 1.1) 查询分配评审及后序阶段包含的所有项目状态
        $statusIds = $this->workflowSvc->getProjectStatusesSincePhase(WorkflowService::PHASE_ASSIGN_REVIEW);
        $statusIdsSQL = $this->joinStringValuesForSQL($statusIds);
        // 1.2）
        // 进步奖 (科技人物奖 不进入网评即不参与分配评审)
        $award_id = Consts::AWARD_TYPE_PROGRESS;
        DB::statement(
            "update applications set status_id = ?, avg_score = null, ranking = null, ranking_percent = null, planned_award_level = '', final_award_level = '' where large_group_id = $largeGroupId and status_id in $statusIdsSQL and award_id = $award_id",
            [Project::STATUS_ASSIGN_REVIEW_TO_ASSIGN]
        );
        // 2) 修改工作流阶段的状态
        // 2.1) 查询分配评审阶段的所有后序阶段列表，
        $phaseIds = $this->workflowSvc->getDescendingPhases(WorkflowService::PHASE_ASSIGN_REVIEW, false);
        $phaseIdsSQL = $this->joinStringValuesForSQL($phaseIds);
        // 2.2)
        DB::statement(
            "update workflow_phases set has_begun = 1, has_ended = 0 where phase_id = ? and large_group_id = $largeGroupId",
            [WorkflowService::PHASE_ASSIGN_REVIEW]
        );
        DB::statement("update workflow_phases set has_begun = 0, has_ended = 0 where phase_id in $phaseIdsSQL and large_group_id = $largeGroupId");
        // 3) 删除 专家组:
        DB::statement("delete from reviewer_groups where large_group_id = $largeGroupId");
        // 4) 删除 专家组-专家关系:
        DB::statement("delete from reviewer_group_reviewers where large_group_id = $largeGroupId");
        // 5) 删除 专家组-项目关系:
        DB::statement("delete from reviewer_group_projects where large_group_id = $largeGroupId");
        // 6) 删除 专家评分项目数据:
        DB::statement("delete from reviewer_score_projects where large_group_id = $largeGroupId");
//        // 7) 删除 待定区投票数据:
//        DB::statement("delete from commissioner_vote_1 where large_group_id = $largeGroupId");
//        // 8）删除 终轮投票数据:
//        DB::statement("delete from commissioner_vote_2 where large_group_id = $largeGroupId");
        // 9) 删除 会评信息
        DB::statement("delete from meeting_review_projects where large_group_id = $largeGroupId");
        DB::statement("update applications set ranking=0,ranking_percent=0,review_ranking=0,meeting_ranking=0,meeting_initial_ranking=0 where large_group_id = $largeGroupId");
    }

    /**
     * 重置到网评待组长审核状态
     * @param $largeGroupId
     */
    public function resetSystemDataToExpertReviewToLeaderReview($largeGroupId)
    {
        // 删除 答辩 数据
        DB::delete("delete from defense_projects where large_group_id = $largeGroupId");

        // 删除 准备答辩 数据
        DB::delete("delete from candidate_defense_projects where large_group_id = $largeGroupId");

        // 删除 投票 数据
        DB::delete("delete from commissioner_project_votes where large_group_id = $largeGroupId");

        // 删除 会评 数据
        DB::delete("delete from meeting_review_projects where large_group_id = $largeGroupId");

        // 重置 大组长审核专家评分的数据
        $scoreStatusRange = $this->joinStringValuesForSQL([ReviewerGroupProject::SCORE_STATUS_LEADER_REVIEW_PASSED, ReviewerGroupProject::SCORE_STATUS_LEADER_REVIEW_REJECTED]);
        DB::update("update reviewer_group_projects set score_status = ?, large_group_leader_review_result = '', large_group_leader_review_remark = '' where large_group_id = $largeGroupId and score_status", [ReviewerGroupProject::SCORE_STATUS_TO_LEADER_REVIEW]);

        // 重置 项目状态
        $statusIdsSinceExpertReview = $this->workflowSvc->getProjectStatusesSincePhase(WorkflowService::PHASE_EXPERT_REVIEW);
        $statusIds = array_values(array_diff($statusIdsSinceExpertReview,
            [Project::STATUS_EXPERT_REVIEW_TO_SCORE, Project::STATUS_EXPERT_REVIEW_ABNORMAL_SCORES, Project::STATUS_EXPERT_REVIEW_TO_LEADER_REVIEW]));
        $statusIdRange = $this->joinStringValuesForSQL($statusIds);
        DB::update("update applications set status_id = ?, planned_award_level = '', final_award_level = '', voted_award_level = '' where large_group_id = $largeGroupId and status_id in $statusIdRange", [Project::STATUS_EXPERT_REVIEW_TO_LEADER_REVIEW]);

        // 修改阶段状态
        $phaseIds = [WorkflowService::PHASE_AWARD, WorkflowService::PHASE_DEFENSE, WorkflowService::PHASE_PREPARE_DEFENSE,
            WorkflowService::PHASE_VOTE, WorkflowService::PHASE_MEETING_REVIEW];
        foreach ($phaseIds as $phaseId) {
            $this->workflowSvc->updatePhaseStatus($phaseId, $largeGroupId, false, false, false);
        }
        DB::update("update workflow_phases set has_ended = 0 where phase_id = ? and large_group_id = ?", [WorkflowService::PHASE_EXPERT_REVIEW, $largeGroupId]);
    }

    /**
     * 填充并提交专家评分
     */
    public function autoFillAndSubmitScores($largeGroupId)
    {
        // for record in reviewer_score_projects where large_group_id = $largeGroupId
        $scoreRecords = ReviewerScoreProject::where('large_group_id', $largeGroupId)->get();
        foreach ($scoreRecords as $record) {
            $scoreData = $this->makeScoreData($record->reviewer_id, $record->project_id);
            $this->reviewSvc->saveProjectScore($scoreData);
            $this->reviewSvc->submitProjectScore($record->reviewer_id, $record->project_id);
        }
    }

    private function makeScoreData($reviewerId, $projectId)
    {
        $project = Project::find($projectId);
        if ($project->award_id == 1) {
            $scores = [
                ['key' => '1', 'evaluation_index' => '技术创新', 'standard_score' => 60, 'real_score' => $this->makeScore(60), 'remarks' => $this->makeRemark()],
                ['key' => '2', 'evaluation_index' => '成果应用', 'standard_score' => 15, 'real_score' => $this->makeScore(15), 'remarks' => $this->makeRemark()],
                ['key' => '3', 'evaluation_index' => '经济与社会效益', 'standard_score' => 15, 'real_score' => $this->makeScore(15), 'remarks' => $this->makeRemark()],
                ['key' => '4', 'evaluation_index' => '推广应用前景', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
            ];
        } else {
            $scores = [
                ['key' => '1', 'evaluation_index' => '所获科技奖励', 'standard_score' => 20, 'real_score' => $this->makeScore(20), 'remarks' => $this->makeRemark()],
                ['key' => '2', 'evaluation_index' => '所获个人荣誉', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
                ['key' => '3', 'evaluation_index' => '发表论文和专著', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
                ['key' => '4', 'evaluation_index' => '所获知识产权证书', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
                ['key' => '5', 'evaluation_index' => '主持科研项目情况', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
                ['key' => '6', 'evaluation_index' => '主持或参与重大工程技术项目情况', 'standard_score' => 30, 'real_score' => $this->makeScore(30), 'remarks' => $this->makeRemark()],
                ['key' => '7', 'evaluation_index' => '科技成果推广应用', 'standard_score' => 10, 'real_score' => $this->makeScore(10), 'remarks' => $this->makeRemark()],
            ];
        }
        $scoreData = [
            'reviewer_id' => $reviewerId,
            'project_id' => $projectId,
            'score' => $this->sumArrayByKey($scores, 'real_score'),
            'form_data' => ['scores' => $scores],
            'is_evidence_material_valid' => rand(0, 100) < 90 ? 1 : 0,
            'remark' => $this->makeRemark(),
        ];
        return $scoreData;
    }

    /**
     * 自动进行专家评审
     * @param $largeGroupId
     * @author: lxy
     * @time: 2020/6/11 7:18 下午
     * @流程:
     */
    public function autoExpertReview($largeGroupId){
        $scoreRecords = ReviewerScoreProject::where('large_group_id', $largeGroupId)->get();

        $time = time() - rand(10,1000);
        ReviewerScoreProject::where('large_group_id', $largeGroupId)
            ->update(['score_begin_at'=> $time]);

        foreach ($scoreRecords as $record) {
            $scoreData = $this->makeScoreData($record->reviewer_id, $record->project_id);
            $this->reviewSvc->saveProjectScore($scoreData);
        }
    }

    /**
     * 提交所有专家的评审结果
     */
    public function submitExpertReview($largeGroupId){
        $scoreRecords = ReviewerScoreProject::where('large_group_id', $largeGroupId)->get();
        foreach ($scoreRecords as $record) {
            $this->reviewSvc->submitProjectScore($record->reviewer_id, $record->project_id);
        }
    }

    /**
     * 重置到网评阶段
     */
    public function resetSystemDataToReview($largeGroupId){
        // 进步奖 (科技人物奖 不进入网评即不参与分配评审)
        $award_id = Consts::AWARD_TYPE_PROGRESS;
        // 将组内项目设置为待评分阶段 D1
        DB::statement(
            "update applications set status_id = ?, avg_score = null, ranking = null, ranking_percent = null, planned_award_level = '', final_award_level = '' where large_group_id = $largeGroupId and award_id = $award_id",
            [Project::STATUS_EXPERT_REVIEW_TO_SCORE]
        );

        // 2) 将工作阶段设置为 网评
        DB::statement(
            "update workflow_phases set has_begun = 1, has_ended = 0 where phase_id = ? and large_group_id = $largeGroupId",
            [WorkflowService::PHASE_EXPERT_REVIEW]
        );
        // 2.2) 将大组后续阶段设置为未开始
        $phaseAry = [
            WorkflowService::PHASE_MEETING_REVIEW,
            WorkflowService::PHASE_PLAN_AWARD,
            WorkflowService::PHASE_VOTE,
            WorkflowService::PHASE_PREPARE_DEFENSE,
            WorkflowService::PHASE_DEFENSE,
            WorkflowService::PHASE_AWARD,
        ];

        $phaseStr = $this->joinStringValuesForSQL($phaseAry);
        DB::statement("update workflow_phases set has_begun = 0, has_ended = 0 where large_group_id = $largeGroupId and phase_id in $phaseStr");
        // 3) 删除 专家组:
        $res = DB::statement("delete from reviewer_groups where large_group_id = $largeGroupId");
        // 4) 删除 专家组-专家关系:
        DB::statement("delete from reviewer_group_reviewers where large_group_id = $largeGroupId");
        // 5) 删除 专家组-项目关系:
        DB::statement("delete from reviewer_group_projects where large_group_id = $largeGroupId");
        // 6) 删除 专家评分项目数据:
        DB::statement("delete from reviewer_score_projects where large_group_id = $largeGroupId");
        // 7) 删除 待定区投票数据:
        DB::statement("delete from commissioner_vote_1 where large_group_id = $largeGroupId");
    }

    /**
     * 大组内所有专家能参加评审
     * @author: lxy
     * @time: 2020/6/12 2:04 下午
     * @流程:
     */
//    public function setAllExpertAbleToReview($largeGroupId) {
//        if ($this->workflowSvc->notAtPhases([WorkflowService::PHASE_ASSIGN_REVIEW], $largeGroupId)) {
//            return ['code' => 3, 'msg' => '现在不是分配评审阶段，不能修改专家的能否参加评审状态'];
//        }
//    }

    /**
     * 自动完成大组长审核专家打分
     */
    public function autoReviewExpertReviewResult($largeGroupId)
    {
        $statusIds = [Project::STATUS_EXPERT_REVIEW_TO_LEADER_REVIEW];
        $projects = Project::where('large_group_id', $largeGroupId)
            ->whereIn('status_id', $statusIds)
            ->get();
        foreach ($projects as $project) {
            $this->manageLargeGroupSvc->leaderReviewExpertReviewResult($project->id,
                rand(0, 100) < 80 ? ReviewerGroupProject::LEADER_REVIEW_RESULT_PASSED : ReviewerGroupProject::LEADER_REVIEW_RESULT_REJECTED,
                $this->makeRemark());
        }
    }

    /**
     * 委员待定区投票
     */
    public function autoVote1($largeGroupId)
    {
//        for record in commissioner_vote_1 where large_group_id = $largeGroupId
        $rows = DB::table('commissioner_vote_1')
            ->where('large_group_id', $largeGroupId)
            ->get();
        foreach ($rows as $row) {
            $this->manageLargeGroupSvc->committeeVote1($row->commissioner_id, $row->project_id, ['result' => rand(0, 100) < 80 ? '同意' : '不同意', 'remark' => $this->makeRemark()]);
        }
    }

    /**
     * 委员投票
     */
    public function autoVote($largeGroupId)
    {
//        for record in commissioner_vote_2 where large_group_id = $largeGroupId
        $rows = DB::table('commissioner_project_votes')
            ->where('large_group_id', $largeGroupId)
            ->get();
        foreach ($rows as $row) {
            (new ProjectService())->committeeVote([
                'commissioner_id' => $row->commissioner_id,
                'project_id' => $row->project_id,
                'result' => rand(0, 100) < 80 ? '同意' : '不同意',
                'remark' => $this->makeRemark()]);
        }
    }

    public function autoSelectDefenseProjects($largeGroupId) {
        $projectIds = DB::table('candidate_defense_projects')->where('large_group_id', $largeGroupId)->pluck('project_id');
        $selectedProjectIds = [];
        $unselectedProjectIds = [];
        foreach ($projectIds as $projectId) {
            if (rand(0, 100) < 67) {
                $selectedProjectIds[] = $projectId;
            } else {
                $unselectedProjectIds[] = $projectId;
            }
        }
        DB::table('candidate_defense_projects')->whereIn('project_id', $selectedProjectIds)->update(['is_selected' => 1]);
        DB::table('candidate_defense_projects')->whereIn('project_id', $unselectedProjectIds)->update(['is_selected' => 0]);
    }

    public function autoUpdateDefenseAwardLevel($largeGroupId) {
        $projectIds = DB::table('defense_projects')->where('large_group_id', $largeGroupId)->pluck('project_id');
        foreach ($projectIds as $projectId) {
            $this->manageLargeGroupSvc->updateDefenseAwardLevel($projectId,
                rand(0, 100) < 25 ? App\Consts::PROGRESS_AWARD_SPECIAL : App\Consts::PROGRESS_AWARD_LEVEL1);
        }
    }

    private function makeScore($fullScore)
    {
        $min = (int)($fullScore * .6);
        $max = (int)($fullScore * .8);
        return rand($min, $max);
    }

    private function sumArrayByKey($array, $key)
    {
        $result = 0;
        foreach ($array as $item) {
            $result += $item[$key];
        }
        return $result;
    }

    private function makeRemark()
    {
        return '测试意见文本' . rand(12345, 54321);
    }

    private function joinStringValuesForSQL($values)
    {
        return '(' . implode(',', array_map(function ($value) {
                return "'$value'";
            }, $values)) . ')';
    }

    private function debug($message)
    {
        if (App::runningInConsole()) {
            echo "$message\n";
        }
    }

}